package game;

import game.Gamemode.TeamDeathmatchManager;
import game.Map.Map;
import game.Player.*;
import game.Rendering.Camera;
import game.Rendering.PointLight;
import game.Sprites.Sprite;

import java.awt.*;
import java.io.IOException;
import java.util.*;
import java.util.List;

public class Scene {
    protected static Scene instance;
    private List<SceneObject> objectList;
    private List<PointLight> lights;

    private game.Map.Map map;
    private List<Sprite> sprites;

    private Camera camera;
    private Color ambientLight;

    public Scene(Map map) throws Exception {
        // SET Scene.instance
        if (Scene.instance != null) {
            throw new Exception("Scene instance not null. Delete first scene before creating another one.");
        }
        Scene.instance = this;
        Helper.mainScene = this;
        this.map = map;


        // Instantiate object list and sprite list
        this.objectList = new ArrayList<SceneObject>();
        this.sprites = new ArrayList<Sprite>();
        this.lights = new ArrayList<PointLight>();

        //TeamDeathmatchManager tdm2 = new TeamDeathmatchManager(maxTeamRounds,maxWonRounds,false,0);
        ambientLight = Color.white;
        Vector3 worldCenter = new Vector3(0,0, 0);
        camera = new Camera(this, worldCenter, 15);
    }

    public void destroy(){
        List<SceneObject> toDestroy = new ArrayList<>(objectList);
        for(int i = 0; i< toDestroy.size(); i++){
            SceneObject obj = toDestroy.get(i);
            obj.destroy();
        }
        if(Scene.instance == this) {
            Scene.instance = null;
            Helper.mainScene = null;
            Helper.myCamera = null;
        }
    }

    public void finalize() {
        if(Scene.instance == this)Scene.instance = null;
    }

    public static Scene getInstance() {
        return Scene.instance;
    }

    public void registerSceneObject(SceneObject obj) {
        this.objectList.add(obj);
    }

    public void deleteSceneObject(SceneObject obj) {
        this.objectList.remove(obj);
    }

    public void registerSprite(Sprite s) {
        this.sprites.add(s);
    }

    public void deleteSprite(Object o) {
        sprites.remove(o);
    }

    public void registerLight(PointLight obj) {
        this.lights.add(obj);
    }

    public void deleteLight(PointLight obj) {
        this.lights.remove(obj);
    }

    /**
     * @return The list of all the sprites in the scene
     */
    public List<Sprite> getSprites() {
        return this.sprites;
    }

    /**
     * @return The list of all the lights in the scene
     */
    public List<PointLight> getLights() {
        return this.lights;
    }

    /**
     * @return The main camera in the scene
     */
    public Camera getCamera() {
        return this.camera;
    }

    /**
     * @return The map in the scene
     */
    public Map getMap() {
        return this.map;
    }

    /**
     * @return The ambient light in the scene
     */
    public Color getAmbientLight() {
        return this.ambientLight;
    }

    public void update(double deltaTime) {
        Helper.mainScene = this;

        // Call update on all objects
        //System.out.println("Objects: " + objectList.size());
        for (int i = 0; i < objectList.size(); i++) {
            //System.out.println("Number of objects inside loop: " + objectList.size());
            //System.out.println("Working on object: " + i);
            SceneObject s = objectList.get(i);
            //System.out.println(s.getClass());
            s.update(deltaTime);
        }
        //System.out.println("INTERMEDIATE SCENE UPDATE");
        // Call late update on all objects
        for (int i = 0; i < objectList.size(); i++) {
            SceneObject s = objectList.get(i);
            s.lateupdate(deltaTime);
        }
        //System.out.println("SCENE UPDATE");
    }


}
